home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
X User Tools
/
X User Tools (O'Reilly and Associates)(1994).ISO
/
sources
/
xcol
/
part01.z
/
part01
Wrap
Internet Message Format
|
1994-09-27
|
34KB
Path: j.cc.purdue.edu!mentor.cc.purdue.edu!purdue!mailrus!uunet!cs.utexas.edu!samsung!brutus.cs.uiuc.edu!apple!sun-barr!newstop!sun!informatik.uni-kl.de
From: hoenig@informatik.uni-kl.de (Helmut Hoenig)
Newsgroups: comp.sources.x
Subject: v06i047: Xcol -- Color-Selector, Part01/02
Message-ID: <133326@sun.Eng.Sun.COM>
Date: 22 Mar 90 18:57:36 GMT
Sender: news@sun.Eng.Sun.COM
Lines: 1159
Approved: argv@sun.com
Submitted-by: Helmut Hoenig <hoenig@informatik.uni-kl.de>
Posting-number: Volume 6, Issue 47
Archive-name: xcol/part01
XCol is a program to edit occurrences of color-names in text-files
(i.e. the '.twmrc'-file). It shows the available colors and you can
change the textfile by selecting new colors with the mouse.
Even without editing a textfile, it gives you a good impression
of the available colors (the colors defined in the 'rgb.txt'-file
of the server).
The program runs on X11R4. It should run on X11R3 too, but I
already had some small problems with the created colormap.
A manual page is included.
by Helmut Hoenig
hoenig@informatik.uni-kl.de
-------------------------------------------------------------------
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: xcol.txt makefile Imakefile patchlevel.h xcol.part1
# Wrapped by hoenig@popper on Wed Mar 21 16:47:26 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f xcol.txt -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"xcol.txt\"
else
echo shar: Extracting \"xcol.txt\" \(3824 characters\)
sed "s/^X//" >xcol.txt <<'END_OF_xcol.txt'
XNAME
X xcol - change color-entries in textfiles
X
XSYNOPSIS
X xcol [-options ...] [filename]
X
XDESCRIPTION
X XCol displays the colors defined in the rgb.txt-file of the
X XServer. The colors are sorted by their names and their
X RGB-values and shown in a cube in the ColorView-Window (The
X positions represent the RGB-values). Since there usually
X are more colors defined in the file than cells in the color-
X map, entries with the same name but different RGB-values for
X different intensities, are grouped together.
X
X If a filename is given as a parameter, all occurrences of
X color-names in that file are shown in an additional
X TextView-Window. To change the colors, a text-line has to be
X made active. Afterwards a new color can be selected in the
X ColorView-Window. To get a better impression of the color, a
X help-color (background) can be selected for each text-line.
X If 2 lines define a foreground and a background color, an
X association can be made and the colors of both lines can be
X selected together.
X
XBUTTONS
X in ColorView-Window
X
X left: select color for the active line.
X middle: select help-color for the active line.
X right: warp pointer to color of active line.
X
X in TextView-Window
X
X left: select line as active line.
X middle: toggle reverse-mode or
X connect/disconnect 2 lines.
X right: show line in the textfile.
X
XOPTIONS
X -rv Color-positions are reversed in the cube. Some new
X colors can become visible in the area of the very
X bright colors.
X
X -b<n> The size of color blocks is set to the constant <n>.
X By default, it depends on the size of the
X ColorView-Window.
X
X -gran<n>
X The maximum number of associated colors is set to
X <n>. By default, this value is 11. (You can see the
X effect when reaching the grey-field, where 101
X associated entries are possibly available.)
X
X -dark<n>
X The percentage of the intensity of other colors can
X be set (default: 50). It is easier to select a
X color, if the screen is darkened a little bit.
X
X +<char_list>
X add characters to list of 'space'-chars. The color-
X string in the textfile has to occur between 2
X 'space'-chars to be recognized. By default, these
X letters are ' ', '\t', '\n', ':', '"'.
X
X -strings
X Names of colors in the file are only recognized when
X used in a string (useful for C-Sources). This means
X that the list of 'space'-chars is set to '"' only.
X
X -case All occurrences of color-names in wrong case are
X replaced by the color-name of the 'rgb.txt'-file.
X
X -help print some instructions (usage of buttons).
X
X -file <name>
X name of a different 'rgb.txt'-file.
X
XFILES
X /usr/lib/X11/rgb.txt
X
XSEE ALSO
X X(1)
X
XBUGS
X Actually I wanted the program to work with the selection
X mechanism used in xterm (when no textfile is given), but it
X seems to be too complicated to use it here. So, the current
X version always stores the string of the color in
X CUT_BUFFER0. If anyone has an easy way to use the correct
X selection mechanism, please inform me.
X
XCOPYRIGHT
X Copyright 1990, University of Kaiserslautern.
X
X Author: Helmut Hoenig (hoenig@informatik.uni-kl.de)
X
X Permission to use, copy, modify, and distribute this
X software for any purpose and without fee is hereby granted,
X provided that the above copyright notice appear in all
X copies.
END_OF_xcol.txt
if test 3824 -ne `wc -c <xcol.txt`; then
echo shar: \"xcol.txt\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f makefile -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"makefile\"
else
echo shar: Extracting \"makefile\" \(99 characters\)
sed "s/^X//" >makefile <<'END_OF_makefile'
XCFLAGS =
XLIBS = -lX11
XG_OBJ = xcol.o
X
Xxcol: $(G_OBJ)
X $(CC) $(CFLAGS) $(G_OBJ) $(LIBS) -o xcol
END_OF_makefile
if test 99 -ne `wc -c <makefile`; then
echo shar: \"makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Imakefile -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"Imakefile\"
else
echo shar: Extracting \"Imakefile\" \(78 characters\)
sed "s/^X//" >Imakefile <<'END_OF_Imakefile'
X SRCS = xcol.c
X OBJS = xcol.o
X
XComplexProgramTarget(xcol)
END_OF_Imakefile
if test 78 -ne `wc -c <Imakefile`; then
echo shar: \"Imakefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f patchlevel.h -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"patchlevel.h\"
else
echo shar: Extracting \"patchlevel.h\" \(53 characters\)
sed "s/^X//" >patchlevel.h <<'END_OF_patchlevel.h'
X#define PATCHLEVEL 0
X#define PATCHDATE "Mar-21-1990"
END_OF_patchlevel.h
if test 53 -ne `wc -c <patchlevel.h`; then
echo shar: \"patchlevel.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f xcol.part1 -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"xcol.part1\"
else
echo shar: Extracting \"xcol.part1\" \(24317 characters\)
sed "s/^X//" >xcol.part1 <<'END_OF_xcol.part1'
X/****************************************************************
X * *
X * xcol - program to edit color-name-occurrences in textfiles *
X * *
X * Written by Helmut Hoenig, Feb. 1990. *
X * University of Kaiserslautern, Germany *
X * *
X * email: hoenig@informatik.uni-kl.de *
X * *
X ****************************************************************/
X
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/cursorfont.h>
X
X#include <sys/param.h>
X#include <stdio.h>
X#include <strings.h>
X#include <ctype.h>
X
X#include "patchlevel.h"
X
X/*----------------------------------------------------------------------------*/
X
X#define COLOR_FONT "-adobe-times-bold-r-normal--17-120-100-100-p-88-iso8859-1"
X#define TEXT_FONT "-adobe-times-bold-r-normal--12-120-75-75-p-67-iso8859-1"
X
X#define RGB_FILE "/usr/lib/X11/rgb.txt"
X
X/* MAX_??? - definitions are used in the definition of some local arrays,
X where I didn't want to make complicated memory allocation. */
X
X#define MAX_CELLS 256 /* number of cells, used by the programm*/
X
X#define MAX_COLS 1000 /* colors in rgb.txt-file */
X#define MAX_COLOR_LINES 400 /* color occurrences in a textfile */
X#define MAX_LINE_LENGTH 1000 /* linelength of textfile */
X
X/*----------------------------------------------------------------------------*/
X
X/* switch on/off some bugs ?? */
X#define CHG_TEXT_WINDOW_COLORMAP
X#define _RECOLOR_CURSOR
X
X/* variables for parameters (default is set) */
Xint reverse = 0;
Xint BO_def = 0;
Xint darkness=50;
Xint gran =11;
Xint original= 0;
X
X/* X-Data */
XDisplay *display;
XScreen *screen;
XXFontStruct *finfo;
XGC gc;
Xint cells;
X
X/* the grey-pixmap is used to get an impression of mixing the foreground
X * and background color of a color-line.
X */
X#define grey_width 16
X#define grey_height 16
Xstatic char grey_bits[] = {
X 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
X 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
X 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
X 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa};
XPixmap grey_pixmap;
X
XCursor mw_cursor; /* Cursor in main-window */
XCursor tw_cursor; /* Cursor in text-window */
XCursor subsel_cursor; /* Cursor during selection of associated colors */
XCursor text_cursor; /* Cursor while looking in the source-file */
XCursor quest_cursor; /* Cursor while asking for write-confirmation */
XCursor updown_cursor; /* Cursor while making association */
X
X/* Mainwindow-Data */
XWindow mw; /* Window-Id */
Xint dx, dy; /* current size of the window */
Xint BO=14; /* current size of the color-boxes in the window */
X
X/* Textwindow-Data */
XWindow tw = NULL;
XXFontStruct *tinfo; /* Structure of the textfont */
Xint char_width, char_height;/* char-size depending on the font */
Xchar *tw_message[2]; /* messages in header and footer-line */
Xint twidth; /* width in pixel */
Xint tw_lines; /* height in lines (header&footer not included) */
Xint act_line=0; /* active-line */
Xint act_offset=0; /* first color-line (when not all lines fit in the window) */
X
X/* Subwindow-Data (little window for selected color) */
XWindow subw; /* Window-Id */
Xint sdx, sdy; /* current size of subwindow */
Xint subcols; /* number of associated colors in the subwindow */
X
X/* Color-Management */
XColormap my_map=NULL;
Xint my_pixel[MAX_CELLS]; /* flag: 0 = pixel not used in my program */
Xint only_mine; /* flag: 1 = allocations only in own map */
X
X#define NotAllocated (-1L)
X#define Undefined (-2L)
X
Xtypedef struct _color_def {
X int r, g, b; /* rgb-value from the 'rbg.txt'-file */
X char *name; /* name from the 'rgb.txt'-file */
X int x, y; /* position in main window */
X unsigned long pixel; /* allocated pixel for the color */
X struct _color_def *associated; /* colors with different intensity (e.g. 'blue' -> 'blue4' ... ) */
X struct _color_def *brother; /* colors with different name (e.g. 'OldLace' -> 'old lace') */
X} ColorDef;
X
Xtypedef struct _color_strings {
X char *name;
X int length;
X ColorDef *def;
X} ColorString;
X
XColorDef *color[MAX_COLS]; /* field with the definitions of the colors */
XColorString cname[MAX_COLS]; /* sorted field with the names of all colors */
XColorString *first[256]; /* 'Hash-Table', points to the first name
X that starts with the given letter. */
X
Xint color_names; /* number of color-names
X = entries in the 'rgb.txt'-file */
Xint color_number; /* number of 'different' colors
X = number of colors shown in the cube */
X
X#define BLACK_STRING "black"
X#define WHITE_STRING "white"
X#define GREY_STRING "gray"
X
XColorDef std_black = { 0, 0, 0, BLACK_STRING };
XColorDef std_white = { 255, 255, 255, WHITE_STRING };
XColorDef std_grey = { 192, 192, 192, GREY_STRING };
X
Xunsigned long white, black, grey; /* pixel-values (in my_map !!) */
XColorDef *back_def; /* default background in textwindow */
X
X/*----------------------------------------------------------------------------*/
X
Xtypedef struct _text_line { /* structure to store the text-file */
X char *contents;
X struct _text_line *next;
X struct _text_line *previous;
X} TextLine;
X
Xtypedef struct _color_line { /* structure for a line with color-entry */
X TextLine *line; /* pointer to the textline */
X ColorDef *color; /* the color defined in the line */
X ColorDef *help; /* a help-color for the background */
X int reverse; /* flag to display line in reverse */
X int pos_in_line; /* position of the color-name in the line */
X int assoc; /* corresponding color-line, when a
X 'foreground-background'-association
X was found (or entered) */
X} ColorLine;
X
Xchar *file_name; /* name of the text-file */
XTextLine *loaded_text; /* Pointer to the first line */
XColorLine line[MAX_COLOR_LINES]; /* array of the color-lines */
Xint color_lines; /* number of the color-lines */
Xint longest_colored; /* length of the longest color-line */
X
Xchar space_char[256]; /* flag, which chars should be recognized
X as spaces */
X
X
X/********************************************************************************
X * parsing the text-file (not very efficient, but who cares) *
X ********************************************************************************/
X
X
Xvoid set_default_spaces()
X{
X memset( space_char, 0, (int)sizeof(space_char) );
X space_char[ ' ' ] = space_char[ '\t' ] = space_char[ '\n' ] =
X space_char[ ':' ] = space_char[ '"' ] = 1;
X}
X
Xint strncase_equal( s1, s2, n )
X register char *s1;
X register char *s2;
X register int n;
X/* the function is NOT correct, since just proves, if strings are equal
X when the 5th bit of their characters is ignored.
X */
X{
X while(n--)
X { if ( ((*s1++)^(*s2++))&((unsigned char)~32) ) return(1);
X }
X return(0);
X}
X
Xint strcase_equal( s1, s2 )
X char *s1,*s2;
X{
Xint n1,n2;
X
X n1 = strlen(s1);
X n2 = strlen(s2);
X if (n1!=n2) return(-1);
X else return(strncase_equal( s1, s2, n1 ));
X}
X
Xstring_exchange( cline, new_color )
X ColorLine *cline;
X ColorDef *new_color;
X/* replaces the color-string in a color-line */
X{
Xchar new_line[MAX_LINE_LENGTH];
Xint pos;
X
X pos = cline->pos_in_line;
X strncpy( &new_line[0], cline->line->contents, pos );
X strcpy( &new_line[pos], new_color->name );
X strcat( new_line, &cline->line->contents[pos+strlen(cline->color->name)] );
X free( cline->line->contents );
X cline->line->contents = (char *)malloc((unsigned) strlen( new_line )+1 );
X strcpy( cline->line->contents, new_line );
X}
X
Xvoid check_colors( in_line )
X TextLine *in_line;
X/* checks, if a color exists in the given line and possibly adds
X * the line to the list of color-lines.
X */
X{
Xint i, c;
Xchar lett;
Xchar check;
XColorString *col;
Xchar *act_line = in_line->contents;
X
X c=strlen(act_line);
X while(c>0)
X { do
X { c--;
X if (space_char[act_line[c-1]]) break;
X }
X while(c>1);
X
X lett = act_line[c];
X if (isalpha(lett))
X {
X if (isupper(lett)) lett = tolower( lett );
X /* compares both cases */
X for (i=0;i<2;i++)
X { for (col=first[lett];col<first[lett+1];col++)
X {
X check = act_line[c+col->length];
X if (space_char[check])
X { if ((strncase_equal( &act_line[c], col->name, col->length )==0 ))
X { line[color_lines].line = in_line;
X line[color_lines].color= col->def;
X line[color_lines].help = back_def;
X line[color_lines].pos_in_line = c;
X line[color_lines].reverse = 0;
X line[color_lines].assoc = -1;
X
X if (original)
X { string_exchange( &line[color_lines], col->def );
X }
X if (XTextWidth( tinfo, act_line, strlen(act_line) )>longest_colored)
X longest_colored = XTextWidth( tinfo, act_line, strlen(act_line) );
X color_lines++;
X return;
X }
X }
X }
X lett = toupper( lett );
X }
X }
X }
X}
X
Xint spc_line( search_string, line, name, length )
X char *search_string;
X TextLine *line;
X char *name;
X int *length;
X/* searches for the search-string in the given line. If it exists, the name
X * in front of the search-string is copied to name and its length is returned.
X */
X{
Xint c, sl, cs;
X
X c = strlen( line->contents );
X sl = strlen(search_string);
X while( c>0 )
X { if (strncase_equal( search_string, &line->contents[c], sl )==0)
X { cs=c;
X do
X { cs--;
X if (isspace(line->contents[cs])) break;
X }
X while(cs>0);
X *length = c-cs;
X if (cs)
X { (*length)--; cs++;
X }
X
X strncpy( name, &line->contents[cs], *length );
X name[*length]='\0';
X return(1);
X }
X c--;
X }
X return(0);
X}
X
Xvoid find_assocs()
X/* tries to find 'Foreground-Background'-Associations in the Color-Lines */
X{
Xint i, j;
Xchar name1[100], name2[100];
Xint length1, length2;
X
X for (i=0;i<color_lines;i++)
X { if (spc_line("foreground", line[i].line, name1, &length1))
X { for (j=i+1;j>=i-1;j-=2)
X { if ((j>=0)&&(j<color_lines))
X { if (spc_line("background", line[j].line, name2, &length2))
X {
X if (strcmp(name1, name2)==0)
X { line[i].reverse=0;
X line[i].help = line[j].color;
X line[i].assoc= j;
X
X line[j].reverse=1;
X line[j].help = line[i].color;
X line[j].assoc= i;
X }
X }
X }
X }
X }
X else if ((spc_line("background", line[i].line, name1, &length1))&&(line[i].assoc<0))
X { for (j=i+1;j>=i-1;j-=2)
X { if ((j>=0)&&(j<color_lines))
X { if (spc_line("border", line[j].line, name2, &length2))
X {
X if (strcmp(name1, name2)==0)
X { line[i].reverse=1;
X line[i].help = line[j].color;
X line[i].assoc= j;
X
X line[j].reverse=0;
X line[j].help = line[i].color;
X line[j].assoc= i;
X }
X }
X }
X }
X }
X }
X}
X
Xint load_file( fname )
X char *fname;
X/* loads the text-file and tries to find color-entries in each line */
X{
XFILE *fp;
XTextLine *act, *next;
Xchar linebuffer[MAX_LINE_LENGTH];
X
X/* load the file with colors */
X longest_colored = 0;
X color_lines = 0;
X
X fp = fopen( fname, "r" );
X if (fp==NULL)
X { fprintf( stderr, "can't load file '%s'.\n", fname );
X return(0);
X }
X
X loaded_text = act = NULL;
X while (fgets( linebuffer, sizeof linebuffer, fp )!=NULL)
X { next = (TextLine *)malloc((unsigned)sizeof(TextLine));
X next->contents = (char *)malloc((unsigned)strlen(linebuffer)+1);
X strcpy( next->contents, linebuffer );
X
X check_colors( next );
X if (act==NULL)
X { loaded_text=act = next;
X next->previous = NULL;
X }
X else
X { act->next = next;
X next->previous = act;
X act = next;
X }
X }
X fclose( fp );
X act->next=NULL;
X return(1);
X}
X
Xint write_file( fname )
X char *fname;
X{
XFILE *fp;
XTextLine *act;
X
X fp = fopen( fname, "w" );
X if (fp==NULL) return(-1);
X act = loaded_text;
X while( act )
X { if (fputs( act->contents, fp )==EOF)
X { fprintf(stderr, "write error on file '%s'\n", fname);
X fclose(fp);
X return(-2);
X }
X act = act->next;
X }
X fclose( fp );
X return(0);
X}
X
X
X/********************************************************************************
X * allocating, freeing, sorting, searching COLORS. *
X ********************************************************************************/
X
X
XColorDef *find_color( name )
X char *name;
X/* searches in the tree of colordefinitions for the named color */
X{
XColorDef *erg, *assoc;
Xint i;
X
X for (i=0;i<color_number;i++)
X { erg = color[i];
X do
X {
X if (strcase_equal(erg->name, name)==0) return( erg );
X assoc = erg->associated;
X while( assoc )
X { if (strcase_equal(assoc->name, name)==0) return( assoc );
X assoc = assoc->associated;
X }
X erg = erg->brother;
X }
X while (erg);
X }
X return(NULL);
X}
X
Xvoid load_color( act )
X ColorDef *act;
X/* allocates a pixel for the color, if it is not already allocated. When it's
X * still possible to allocate pixels in the DefaultColormap, this is done and
X * the same color is stored in both maps. If no more cells are available in
X * the DefaultColormap, the program continues working only in its own map.
X */
X{
XXColor scr;
Xlong pixel;
X
X if (act->pixel==NotAllocated)
X { if (!only_mine)
X { if ( (!XAllocColorCells( display, DefaultColormapOfScreen(screen), True,
X NULL, 0, (unsigned long*)&pixel, 1 )) || (pixel>=cells) )
X {
X for (pixel=0;pixel<cells;pixel++)
X {
X if (my_pixel[pixel])
X { XFreeColors( display, DefaultColormapOfScreen(screen),
X (unsigned long*)&pixel, 1, 0 );
X }
X }
X
X only_mine=1;
X#ifdef CHG_TEXT_WINDOW_COLORMAP
X/* when switched on, all windows (not only the textwindow), are displayed
X * in my Colormap, when the DefaultColormap hasn't got any more cells available.
X * Try the option -gran100 and search for the 'gray'-color in the main-window
X * to reach the extremes of the program.
X */
X if (tw)
X { XSetWindowColormap( display, tw, my_map );
X }
X#endif
X }
X }
X if (only_mine)
X { for (pixel=cells-1;pixel>=0;pixel--)
X { if (my_pixel[pixel]==0) break;
X }
X /* the reaction to an overflow in the color-map is hard, but
X * I can't think of an easy solution for that problem.
X */ if (pixel<0)
X { fprintf( stderr, "You did it. The Colormap if full.\n");
X if (CellsOfScreen(screen)>MAX_CELLS)
X { fprintf( stderr, "Compile the program again with the\n");
X fprintf( stderr, "MAX_CELLS-macro set to an higher value.\n");
X }
X exit(0);
X }
X }
X act -> pixel = pixel;
X scr.pixel = pixel;
X scr.flags = DoRed | DoGreen | DoBlue;
X scr.red = act->r << 8;
X scr.green = act->g << 8;
X scr.blue = act->b << 8;
X XStoreColor( display, my_map, &scr );
X if (!only_mine)
X XStoreColor( display, DefaultColormapOfScreen(screen), &scr );
X }
X my_pixel[act->pixel]++;
X}
X
Xvoid unload_color( act )
X ColorDef *act;
X/* The color is not used anymore. It is possible that the color was loaded
X * more than once and therefor, the cell can't be freed.
X */
X{
X if (act->pixel==NotAllocated) return;
X
X if ((--my_pixel[act->pixel])==0)
X { if (!only_mine)
X { XFreeColors( display, DefaultColormapOfScreen(screen),
X &act->pixel, 1, 0 );
X }
X act->pixel=NotAllocated;
X }
X}
X
Xvoid load_text_colors()
X/* to load all colors used in the color-lines of the text-file */
X{
Xint i;
X
X for (i=0;i<color_lines;i++)
X { load_color( line[i].color );
X load_color( line[i].help );
X }
X}
X
Xvoid exchange( old, new )
X ColorDef **old;
X ColorDef *new;
X/* correct exchanging of a loaded color */
X{
X if (*old)
X { unload_color( *old );
X }
X load_color( new );
X *old = new;
X}
X
X/*----------------------------------------------------------------------------*/
X
X/*
X * functions to sort the colors
X */
X
Xint color_name_sort( p1, p2 )
X ColorString *p1, *p2;
X{
X return(strcmp(p1->name, p2->name));
X}
X
Xint color_sort( p1, p2 )
X ColorDef **p1, **p2;
X{
Xchar *s1, *s2;
X
X if ((*p1)->b!=(*p2)->b) return(((*p1)->b>(*p2)->b)?1:-1);
X if ((*p1)->g!=(*p2)->g) return(((*p1)->g>(*p2)->g)?1:-1);
X if ((*p1)->r!=(*p2)->r) return(((*p1)->r>(*p2)->r)?1:-1);
X s1 = index((*p1)->name, ' ');
X s2 = index((*p2)->name, ' ');
X s1 = s2 = NULL;
X
X if (s1)
X { if (s2) return(strcmp((*p1)->name, (*p2)->name));
X else return(1);
X }
X else
X { if (s2) return(-1);
X else return(strcmp((*p1)->name, (*p2)->name));
X }
X}
X
Xint color_sort_r( p1, p2 )
X ColorDef **p1, **p2;
X{
X if ((*p1)->b!=(*p2)->b) return(((*p1)->b>(*p2)->b)?-1:1);
X if ((*p1)->g!=(*p2)->g) return(((*p1)->g>(*p2)->g)?-1:1);
X if ((*p1)->r!=(*p2)->r) return(((*p1)->r>(*p2)->r)?-1:1);
X return(0);
X}
X
Xvoid brother_sort( first )
X ColorDef **first;
X{
XColorDef *list[1000];
Xint length;
X
X length = 0;
X
X list[length] = *first;
X while(list[length]->brother)
X { list[length+1] = list[length]->brother;
X length++;
X }
X
X qsort( (char *)list, length+1, sizeof(ColorDef *), color_sort );
X
X list[length]->brother = NULL;
X
X while(length>0)
X { list[length-1]->brother = list[length];
X length--;
X }
X *first = list[0];
X}
X
Xvoid associated_sort( first )
X ColorDef *first;
X{
XColorDef *list[1000];
Xint length;
X
X length = 0;
X
X list[length] = first;
X while(list[length]->associated)
X { list[length+1] = list[length]->associated;
X length++;
X }
X
X qsort( (char *)&list[1], length, sizeof(ColorDef *), color_sort );
X
X list[length]->associated = NULL;
X
X while(length>0)
X { list[length-1]->associated = list[length];
X length--;
X }
X}
X
X/*----------------------------------------------------------------------------*/
X
X/*
X * functions to load the color-file and build the tree with colordefinitions
X */
X
Xchar *cut_digits( name )
X char *name;
X/* cuts digits from a color-string. returns a pointer to a static string
X * which of course must not be freed. if there where no digits, the original
X * pointer is returned.
X */
X{
Xstatic char short_name[40];
Xint i;
X
X i = strlen(name);
X if ((i>39)||(!isdigit(name[i-1]))) return(name);
X
X strcpy( short_name, name );
X i--;
X while ((i>0)&&(isdigit(short_name[i])))
X { short_name[i] = '\0';
X i--;
X }
X return(short_name);
X}
X
Xvoid next_name( act )
X ColorDef *act;
X/* collects color-names for the hash-table */
X{
X if (act->pixel==Undefined)
X { fprintf(stderr, "%s not defined.\n", act->name);
X return;
X }
X cname[color_names].name = act->name;
X cname[color_names].length = strlen(act->name);
X cname[color_names].def = act;
X color_names++;
X}
X
XColorDef *make_entry( new )
X ColorDef *new;
X/* allocates space for the data of a new color */
X{
XColorDef *erg;
X
X erg = (ColorDef *)malloc((unsigned) sizeof(ColorDef) );
X memcpy( (char *)erg, (char *)new, sizeof(ColorDef) );
X erg -> associated = NULL;
X erg -> brother = NULL;
X erg -> pixel = NotAllocated;
X
X return( erg );
X}
X
Xvoid new_color( new )
X ColorDef *new;
X/* searches for overlaps in the color-field and stores the new color */
X{
Xchar *search_name;
XColorDef *act;
XColorDef *help;
Xint i;
Xint subname = 0;
X
X search_name = cut_digits( new->name );
X subname = (search_name!=new->name);
X
X act = find_color( search_name );
X
X if (act)
X { if (subname) /* found and associated entry */
X { help = act->associated;
X act->associated = make_entry( new );
X act->associated->associated = help;
X }
X else /* strange: color declared twice ? */
X { if (act->pixel==Undefined)
X { memcpy( (char *)act, (char *)new, sizeof(ColorDef)-2*sizeof(ColorDef *) );
X act->pixel = NotAllocated;
X }
X else
X {
X help = act->brother;
X act->brother = make_entry( new );
X act->brother->brother = help;
X }
X }
X }
X else
X { for (i=0;i<color_number;i++)
X { if ( (new->r==color[i]->r) && (new->g==color[i]->g) && (new->b==color[i]->b) ) break;
X }
X if (i<color_number)
X { help = color[i]->brother;
X color[i]->brother = make_entry( new );
X color[i]->brother->brother = help;
X }
X else
X { if (subname) /* indexed name found before original */
X { act = (ColorDef *)malloc((unsigned) sizeof(ColorDef) );
X memset( (char *)act, (char)-1, sizeof(ColorDef) );
X act->pixel = Undefined;
X act->name = (char *)malloc((unsigned) strlen(search_name)+1 );
X strcpy( act->name, search_name );
X act->associated = make_entry( new );
X act->brother = NULL;
X color[color_number++] = act;
X }
X else /* found new color */
X { color[color_number++] = make_entry( new );
X }
X }
X }
X}
X
Xload_standard( act )
X ColorDef *act;
X{
XXColor exact_def,screen_def;
X
X if (XLookupColor( display, DefaultColormapOfScreen(screen), act->name,
X &exact_def, &screen_def ))
X { act->r = exact_def.red >> 8;
X act->g = exact_def.green >> 8;
X act->b = exact_def.blue >> 8;
X }
X new_color( act );
X}
X
X/*----------------------------------------------------------------------------*/
X
Xupdate_map()
X/* sets unused pixels in my_map to the colors (with different intensity)
X * of the DefaultColormap.
X */
X{
XXColor qcols[MAX_CELLS];
Xint i, j;
X
X j=0;
X for (i=0;i<cells;i++)
X { if (my_pixel[i]==0) qcols[j++].pixel=i;
X }
X XQueryColors( display, DefaultColormapOfScreen(screen), qcols, j );
X for (i=0;i<j;i++)
X { qcols[i].red = ((long)qcols[i].red *darkness)/100;
X qcols[i].green = ((long)qcols[i].green*darkness)/100;
X qcols[i].blue = ((long)qcols[i].blue *darkness)/100;
X qcols[i].flags = DoRed | DoGreen | DoBlue;
X }
X XStoreColors( display, my_map, qcols, j );
X}
X
Xcreate_new_map()
X/* get an own colormap */
X{
Xint i;
XXColor qcols[MAX_CELLS];
Xunsigned long pixel[MAX_CELLS];
X
X/* allocate new colormap and copy the darkened colors of the default-map */
X my_map = XCreateColormap( display, mw,
X XDefaultVisualOfScreen(screen), AllocAll);
X if (my_map==(Colormap)0)
X { fprintf(stderr, "can't create colormap.\n" );
X exit(0);
X }
X memset( (char *)my_pixel, (char)0, sizeof(my_pixel) );
X
X/* copy the default-map */
X for (i=0;i<cells;i++) qcols[i].pixel = i;
X XQueryColors( display, DefaultColormapOfScreen(screen), qcols, cells );
X for (i=0;i<cells;i++)
X { qcols[i].red = ((long)qcols[i].red *darkness)/100;
X qcols[i].green = ((long)qcols[i].green*darkness)/100;
X qcols[i].blue = ((long)qcols[i].blue *darkness)/100;
X qcols[i].flags = DoRed | DoGreen | DoBlue;
X }
X XStoreColors( display, my_map, qcols, cells );
X
X/* try to allocate the color_cells in the default-map */
X if (XAllocColorCells( display, DefaultColormapOfScreen(screen), True,
X NULL, 0, pixel, color_number ))
X { int high_value=0;
X
X /* store the colors into my map and into and into the default-colormap
X * as there are enough cells for both.
X */
X for (i=0;i<color_number;i++)
X { qcols[i].pixel = pixel[i];
X qcols[i].flags = DoRed | DoGreen | DoBlue;
X qcols[i].red = color[i]->r << 8;
X qcols[i].green = color[i]->g << 8;
X qcols[i].blue = color[i]->b << 8;
X color[i]->pixel = pixel[i];
X if (pixel[i]>=cells)
X { high_value=1;
X break;
X }
X my_pixel[pixel[i]]=1;
X }
X
X if (high_value)
X { XFreeColors( display, DefaultColormapOfScreen(screen),
X pixel, color_number, 0 );
X only_mine = 1;
X }
X else
X {
X XStoreColors( display, DefaultColormapOfScreen(screen), qcols, color_number );
X XStoreColors( display, my_map, qcols, color_number );
X only_mine = 0;
X }
X }
X else only_mine = 1;
X
X if (only_mine)
X {
X /* pixels are just used from high to low numbers */
X for (i=0;i<color_number;i++)
X {
X qcols[i].pixel = cells-i-1;
X qcols[i].flags = DoRed | DoGreen | DoBlue;
X qcols[i].red = color[i]->r << 8;
X qcols[i].green = color[i]->g << 8;
X qcols[i].blue = color[i]->b << 8;
X color[i]->pixel = cells-i-1;
X my_pixel[cells-i-1]=1;
X }
X XStoreColors( display, my_map, qcols, color_number );
X
X /* afterwards, all free pixels of the default-map are allocated
X * and set to the values of the new colormap.
X */
X i=0;
X while( XAllocColorCells( display, DefaultColormapOfScreen(screen), True,
X NULL, 0, &pixel[i], 1 ) )
X { qcols[i].pixel = pixel[i];
X i++;
X }
X XQueryColors( display, my_map, qcols, i );
X XStoreColors( display, DefaultColormapOfScreen(screen), qcols, i );
X XFreeColors( display, DefaultColormapOfScreen(screen), pixel, i, 0 );
X only_mine = 1;
X }
X
X/* the pixels for black, white have to be used from my_map, since
X * the entries of the DefaultColormap are possibly darkened.
X */
X black = find_color( BLACK_STRING )->pixel;
X my_pixel[black]++;
X white = find_color( WHITE_STRING )->pixel;
X my_pixel[white]++;
X grey = find_color( GREY_STRING )->pixel;
X my_pixel[grey]++;
X}
X
Xdestroy_colormap()
X/* not used */
X{
Xunsigned long pixel[MAX_CELLS];
Xint i, j;
XColorDef *assoc, *erg;
X
X XFreeColormap( display, my_map );
X j=0;
X if (!only_mine)
X { for (i=0;i<cells;i++)
X { if (my_pixel[i]) pixel[j++] = i;
X }
X XFreeColors( display, DefaultColormapOfScreen(screen), pixel, j, 0 );
X }
X my_map = NULL;
X memset( (char *)my_pixel, (char)0, sizeof(my_pixel) );
X
X for (i=0;i<color_number;i++)
X { erg = color[i];
X do
X { erg->pixel = NotAllocated;
X assoc = erg->associated;
X while( assoc )
X { assoc->pixel = NotAllocated;
X assoc = assoc->associated;
X }
X erg = erg->brother;
X }
X while (erg);
X }
X}
X
X
END_OF_xcol.part1
if test 24317 -ne `wc -c <xcol.part1`; then
echo shar: \"xcol.part1\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
# additional concatenation of splitted file
if test -f xcol.part2 ; then
echo ' concatenation of "xcol.part1" and "xcol.part2" to "xcol.c".'
cat xcol.part1 xcol.part2 > xcol.c
echo ' removing "xcol.part1" and "xcol.part2".'
rm xcol.part1 xcol.part2
else
echo ' unpack the second part now.'
fi
exit 0
dan
-----------------------------------------------------------
O'Reilly && Associates
argv@sun.com / argv@ora.com
632 Petaluma Ave, Sebastopol, CA 95472
800-338-NUTS, in CA: 800-533-NUTS, FAX 707-829-0104
Opinions expressed reflect those of the author only.